﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Kindohm.KSynth.Library;
using System.Diagnostics;

namespace Kindohm.KSynth.UI
{
    public partial class PresetList : UserControl
    {
        bool pressing;
        int pressTick;
        DispatcherTimer timer;
        Border pressedButton;
        const int ElapsedTrigger = 1500;
        Color pressedColor = Color.FromArgb(255, 110, 169, 204);
        Color hasPresetColor = Colors.LightGray;
        Color hasNoPresetColor = Colors.Gray;
        Color hoverColor = Colors.DarkGray;

        //main color = 110 169 204

        public PresetList()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(PresetList_Loaded);
        }

        public Preset Preset { get; set; }

        public VoiceSlider DelaySlider { get; set; }
        public EnvelopeControls EnvelopeControls { get; set; }
        public VoiceControls Voice1Controls { get; set; }
        public VoiceControls Voice2Controls { get; set; }
        public VoiceControls Voice3Controls { get; set; }

        void PresetList_Loaded(object sender, RoutedEventArgs e)
        {
            this.timer = new DispatcherTimer();
            this.timer.Interval = TimeSpan.FromMilliseconds(300);
            this.timer.Tick += new EventHandler(timer_Tick);

            this.LoadButtons();
        }

        void LoadButtons()
        {

            for (int i = 1; i <= 16; i++)
            {
                Border border = new Border();
                border.MouseEnter += new MouseEventHandler(border_MouseEnter);
                border.MouseLeave += new MouseEventHandler(border_MouseLeave);
                border.Style = (Style)App.Current.Resources["presetBorder"];
                TextBlock text = new TextBlock();
                text.Text = i.ToString();
                text.Style = (Style)App.Current.Resources["presetText"];
                border.Child = text;
                this.buttonPanel.Children.Add(border);

                Preset preset = PresetRepository.Instance.FindByNumber(i);

                if (preset != null)
                    border.Background = new SolidColorBrush(hasPresetColor);
                else
                    border.Background = new SolidColorBrush(hasNoPresetColor);

                border.DataContext = preset;
                border.MouseLeftButtonDown += new MouseButtonEventHandler(button_MouseLeftButtonDown);
                border.MouseLeftButtonUp += new MouseButtonEventHandler(button_MouseLeftButtonUp);
            }

            if (PresetRepository.Instance.PresetErrors.Count > 0)
            {
                StringBuilder errors = new StringBuilder();
                for (int x = 0; x < PresetRepository.Instance.PresetErrors.Count; x++)
                    errors.AppendFormat("{0}" + Environment.NewLine, PresetRepository.Instance.PresetErrors[x]);
                MessageBox.Show(errors.ToString());
            }
        }

        void border_MouseLeave(object sender, MouseEventArgs e)
        {
            Border border = (Border)sender;
            if (border != this.pressedButton)
            {
                if (border.DataContext == null)
                    border.Background = new SolidColorBrush(hasNoPresetColor);
                else
                    border.Background = new SolidColorBrush(hasPresetColor);
            }
        }

        void border_MouseEnter(object sender, MouseEventArgs e)
        {
            Border border = (Border)sender;
            if (border != this.pressedButton)
            {
                border.Background = new SolidColorBrush(hoverColor);
            }

        }

        void timer_Tick(object sender, EventArgs e)
        {
            int elapsed = Environment.TickCount - this.pressTick;
            if (this.pressing && elapsed > PresetList.ElapsedTrigger)
            {
                this.timer.Stop();
                this.pressing = false;
                this.SavePreset(pressedButton);
            }
        }

        void button_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Border border = (Border)sender;
            if (border.DataContext == null)
                border.Background = new SolidColorBrush(hasNoPresetColor);
            this.pressing = false;
            this.timer.Stop();
            this.flash.Stop();
            this.Preset = border.DataContext as Preset;
            
            if (this.Preset != null && this.PresetSelected != null)
                this.PresetSelected(this, EventArgs.Empty);
        }

        void button_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Border border = (Border)sender;
            border.Background = new SolidColorBrush(this.pressedColor);
            if (this.pressedButton != null)
            {
                if (this.pressedButton.DataContext == null)
                    this.pressedButton.Background = new SolidColorBrush(hasNoPresetColor);
                else
                    this.pressedButton.Background = new SolidColorBrush(hasPresetColor);
            }
            this.pressedButton = border;
            this.pressTick = Environment.TickCount;
            this.pressing = true;
            this.timer.Start();
        }

        void SavePreset(Border button)
        {
            TextBlock text = (TextBlock)button.Child;
            int number = int.Parse(text.Text);

            Preset preset = new Preset();
            preset.Attack = this.EnvelopeControls.Attack;
            preset.Sustain = this.EnvelopeControls.Sustain;
            preset.Decay = this.EnvelopeControls.Decay;
            preset.PitchShift = this.EnvelopeControls.Pitch;
            preset.Number = number;
            preset.DelayLength = (int)this.DelaySlider.Value;

            preset.VoicePresets.Add(
                this.LoadVoicePreset(this.Voice1Controls));
            preset.VoicePresets.Add(
                this.LoadVoicePreset(this.Voice2Controls));
            preset.VoicePresets.Add(
                this.LoadVoicePreset(this.Voice3Controls));
 
            PresetRepository.Instance.SavePreset(preset);
            button.DataContext = preset;
            SolidColorBrush brush = (SolidColorBrush)button.Background;
            Storyboard.SetTarget(this.flash, brush);
            Storyboard.SetTargetProperty(this.flash, new PropertyPath("Color"));
            this.flash.Begin();

        }

        VoicePreset LoadVoicePreset(VoiceControls controls)
        {
            VoicePreset preset = new VoicePreset();
            preset.Detune = controls.Detune;
            preset.Level = controls.Level;
            preset.Phase = controls.Phase;
            preset.Pan = controls.Pan;
            preset.WaveFormName = controls.SelectedWaveForm.Name;
            return preset;
        }

        public event EventHandler PresetSelected;
    }
}
